package com.taoist_awei.blog.core;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import java.util.HashMap;
import java.util.Map;


/**
 * @author 高威
 * 用于统一返回结果的包装类, 有构造器模式以及Builder模式
 */
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"statusCode", "success", "data", "message", "token"})
@ApiModel(value = "Http返回Model", description = "接口返回Model")
public class HttpResult {
    @JSONField(ordinal = 0)
    @ApiModelProperty(value = "状态码", name = "statusCode", example = "200")
    private Integer statusCode = null;
    @JSONField(ordinal = 3)
    @ApiModelProperty(value = "数据", name = "data", example = "{username: Gao, email: 2592006268@qq.com}")
    private Object data = null;
    @JSONField(ordinal = 4)
    @ApiModelProperty(value = "服务器信息", name = "message", example = "登陆成功")
    private String message = null;
    @JSONField(ordinal = 2)
    @ApiModelProperty(value = "访问Api接口", name = "success", example = "true")
    private Boolean success = null;
    @JSONField(ordinal = 5)
    @ApiModelProperty(value = "token信息", name = "token", example = "token")
    private String token = null;

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }

    public HttpResult(HttpStatus httpStatus, Object data) {
        if (httpStatus.is2xxSuccessful()) {
            this.statusCode = httpStatus.value();
            this.message = "请求成功";
        } else if (httpStatus.is4xxClientError()) {
            this.statusCode = httpStatus.value();
            this.message = "客户端请求错误";
        } else if (httpStatus.is5xxServerError()) {
            this.statusCode = httpStatus.value();
            this.message = "服务端错误";
        } else {
            this.statusCode = httpStatus.value();
            this.message = "未知错误";
        }
        this.data = data;
        this.success = true;
    }

    public HttpResult(HttpResultBuilder builder) {
        this.success = builder.success;
        this.message = builder.message;
        this.data = builder.data;
        this.statusCode = builder.statusCode;
        this.token = builder.token;
    }

    public static class HttpResultBuilder {
        private Integer statusCode = 404;
        private Object data = null;
        private String message = null;
        private Boolean success = true;
        private String token = null;

        public HttpResultBuilder() {

        }

        public HttpResult ok(Object o) {
            return new HttpResultBuilder()
                    .message("请求成功")
                    .statusCode(200)
                    .data(o)
                    .build();
        }


        public HttpResultBuilder ok() {
            this.message("请求成功");
            this.statusCode(200);
            return this;
        }

        public HttpResultBuilder bindingResult(BindingResult bindingResult) {
            StringBuilder builder = new StringBuilder();
            bindingResult.getFieldErrors().forEach( objectError -> {
                builder.append(objectError.getDefaultMessage());
                builder.append(", ");
            });
            builder.delete(builder.length() - 2, builder.length());
            this.statusCode = 400;
            this.success = true;
            Map<String, String> data = new HashMap<>();
            data.put("error", builder.toString());
            this.data(data);
            return this;
        }

        public HttpResultBuilder token(String token) {
            this.token = token;
            return this;
        }

        public HttpResultBuilder statusCode(int code) {
            this.statusCode = code;
            return this;
        }

        public HttpResultBuilder notSuccess() {
            this.success = false;
            return this;
        }

        @SneakyThrows
        public HttpResultBuilder data(Object data) {
            this.data = data;
            return this;
        }

        public HttpResultBuilder message(String message) {
            this.message = message;
            return this;
        }

        public HttpResult build() {
            return new HttpResult(this);
        }
    }
}